package com.sunnay.util;

import com.sunnay.enums.GbCodeEnum;
import com.sunnay.exception.DataException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RPermitExpirableSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class RedisUtil {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    RedissonClient redissonClient;


    public boolean hasKey(String key) {
        try{
            return redisTemplate.hasKey(key);
        }catch (Exception e){
            log.error(key+"判断是否存在出现问题",e);
        }
        return false;
    }

    /**
     * 指定key失效
     * @param redisKey
     * @param timeout
     * @param timeUnit
     */
    public void expire(String redisKey,long timeout,TimeUnit timeUnit) {
        redisTemplate.expire(redisKey, timeout, timeUnit);
    }

    /**
     * 到指定时间才失效
     * @param redisKey
     * @param atDate
     */
    public void expireAt(String redisKey, Date atDate){
        redisTemplate.expireAt(redisKey, atDate);
    }

    /**
     * 获取失效时间 单位:秒
     * @param redisKey
     * @return
     */
    public Long getExpire(String redisKey){
        return redisTemplate.getExpire(redisKey);
    }

    /**
     * 删除Key
     * @param redisKey
     */
    public void deleteRedisKey(String redisKey) {
        try {
            redisTemplate.delete(redisKey);
        } catch (Exception e) {
            log.error(redisKey+"删除出现了问题",e);
        }
    }

    /**
     * 删除多个Key
     * @param redisKeyList
     */
    public void deleteRedisKey(List<String> redisKeyList) {
        try {
            redisTemplate.delete(redisKeyList);
        } catch (Exception e) {
            log.error(StringUtils.join(redisKeyList,",") +"删除出现了问题",e);
        }
    }

    /**
     * 返回key-value的值
     * @param key
     * @return
     */
    public Object getValueObject(String key) {
        try {
            return redisTemplate.boundValueOps(key).get();
        } catch (Exception e) {
            log.error(key+"获取出现了问题",e);
        }
        return null;
    }

    /**
     * 设置 key-value形式的值
     * @param key
     */
    public void setValueObject(String key,Object obj, long l, TimeUnit timeUnit) {
        try {
            redisTemplate.boundValueOps(key).set(obj,l,timeUnit);
        } catch (Exception e) {
            log.error(key+"设置出现了问题",e);
        }
    }

    /**
     * 设置 hash-value形式的值
     * @param key
     * @param hk
     * @param obj
     */
    public Object setHashObject(Object key,Object hk,Object obj){
        try {
            Object o = redisTemplate.boundHashOps(key).get(hk);
            redisTemplate.boundHashOps(key).put(hk,obj);
            return o;
        } catch (Exception e) {
            log.error(key+"哈希设置出现了问题",e);
        }
        return null;
    }

    /**
     * 获取 hash-value形式的值
     * @param key
     * @param hk
     * @return
     */
    public Object getHashObject(Object key,Object hk){
        try {
            return  redisTemplate.boundHashOps(key).get(hk);
        } catch (Exception e) {
            log.error(key+"获取哈希设置出现了问题",e);
        }
        return null;
    }

    /**
     * 获取 hash下有多少个key
     * @param key
     * @return
     */
    public Set getHashKeyList(Object key) {
        try {
            return redisTemplate.boundHashOps(key).keys();
        } catch (Exception e) {
            log.error(key+"获取哈希KeySet出现了问题",e);
        }
        return null;
    }

    /**
     * 删除 hash-value形式的值
     * @param key
     * @param hk
     */
    public void delHashObject(Object key, Object hk) {
        try {
            redisTemplate.boundHashOps(key).delete(hk);
        } catch (Exception e) {
            log.error(key+"删除哈希子Key",e);
        }
    }

    /**
     * 判断hash-value形式中是否存在该key
     * @param key
     * @param hk
     * @return
     */
    public boolean containKeyByHash(Object key, Object hk) {
        Boolean exist = null;
        try {
            exist = redisTemplate.boundHashOps(key).hasKey(hk);
        } catch (Exception e) {
            log.error(key+"判断是否存在hashKey",e);
        }
        if(exist==null||!exist){
            return false;
        }
        return true;
    }

    /**
     * 递增
     * @param key
     * @param hk
     * @param increment
     */
    public void incrementByInt(Object key, Object hk,int increment) {
        try {
            redisTemplate.boundHashOps(key).increment(hk, increment);
        } catch (Exception e) {
            log.error(key+"获取递增设置出现了问题",e);
        }
    }

    /**
     * 获取信号量
     * @param key
     * @param permits
     * @return
     */
    public RPermitExpirableSemaphore getSemaphore(String key,int permits){
        RPermitExpirableSemaphore permitExpirableSemaphore = redissonClient.getPermitExpirableSemaphore(key);
        boolean b = permitExpirableSemaphore.trySetPermits(permits);
        if(!b){
            throw new DataException(GbCodeEnum.SYSTEM_NETWORK_ERROR.getValue()+",key:"+key+"permits:"+permits);
        }
        return permitExpirableSemaphore;
    }

    /**
     * 获取信号量
     * @param key
     * @return
     */
    public RPermitExpirableSemaphore getSemaphore(String key){
        return redissonClient.getPermitExpirableSemaphore(key);
    }

}
